Add 0018-Don-t-let-CEDET-execute-code-from-an-arbitrary-Proje.patch.
authorRob Browning <rlb@defaultvalue.org>
Sun, 29 Jan 2012 19:40:42 +0000 (13:40 -0600)
committerRob Browning <rlb@defaultvalue.org>
Sun, 29 Jan 2012 19:40:47 +0000 (13:40 -0600)
Don't execute arbitrary elisp code from any file named Project.ede in
or above a CEDET-related directory (CVE-2012-0035).

Thanks to Florian Weimer <fw@deneb.enyo.de> for the report.

Closes: #655299
1  2 
debian/.git-dpm
debian/patches/0018-Don-t-let-CEDET-execute-code-from-an-arbitrary-Proje.patch
debian/patches/series

diff --cc debian/.git-dpm
index f10db34eb1eaf74ca71e402677fca6db43c9bba2,0000000000000000000000000000000000000000..e8c69cc36f0a27c01d5fe548f964031d5a2cfd89
mode 100644,000000..100644
--- /dev/null
@@@ -1,8 -1,0 +1,8 @@@
- e46e3fe4cd794f1c1e50a5bc445d184e2f82ce38
- e46e3fe4cd794f1c1e50a5bc445d184e2f82ce38
 +# see git-dpm(1) from git-dpm package
++47b3d66260508d7529dbd401a3e325fd79cf8e3c
++47b3d66260508d7529dbd401a3e325fd79cf8e3c
 +7aee3de6fd6bca44751754b10a338947fa947b1c
 +7aee3de6fd6bca44751754b10a338947fa947b1c
 +emacs23_23.3+1.orig.tar.bz2
 +80b3822579eddfc120641c5a181eb0b5c7a0667d
 +23065394
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7fcd1cfc136a3701f02b692886349baee7224131
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,429 @@@
++From 47b3d66260508d7529dbd401a3e325fd79cf8e3c Mon Sep 17 00:00:00 2001
++From: Rob Browning <rlb@defaultvalue.org>
++Date: Sun, 29 Jan 2012 13:40:38 -0600
++Subject: Don't let CEDET execute code from an arbitrary Project.ede file.
++
++CEDET will no longer execute arbitrary elisp code from any file named
++Project.ede that it finds in or above a CEDET-related directory
++(CVE-2012-0035).
++
++Provided-by: Florian Weimer <fw@deneb.enyo.de>
++Date: Tue, 10 Jan 2012 07:50:49 +0100
++Applied-by: Rob Browning <rlb@defaultvalue.org>
++Applied-Upstream: http://bzr.savannah.gnu.org/lh/emacs/emacs-23/revision/100631
++Bug-Debian: http://bugs.debian.org/655299
++Closes: #655299
++---
++ lisp/cedet/ChangeLog     |   17 ++++
++ lisp/cedet/ede.el        |  215 +++++++++++++++++++++++++++++++++++-----------
++ lisp/cedet/ede/auto.el   |   28 ++++++-
++ lisp/cedet/ede/simple.el |    3 +-
++ 4 files changed, 211 insertions(+), 52 deletions(-)
++
++diff --git a/lisp/cedet/ChangeLog b/lisp/cedet/ChangeLog
++index 2d0cbb8..9b8e992 100644
++--- a/lisp/cedet/ChangeLog
+++++ b/lisp/cedet/ChangeLog
++@@ -1,3 +1,20 @@
+++2012-01-09  Eric Ludlam  <zappo@gnu.org>
+++
+++     * ede.el (ede-project-directories): New option.
+++     (ede-directory-safe-p): Check it.
+++     (ede-initialize-state-current-buffer, ede, ede-new)
+++     (ede-check-project-directory, ede-rescan-toplevel)
+++     (ede-load-project-file, ede-parent-project, ede-current-project):
+++     (ede-target-parent): Avoid loading in a project unless it is safe,
+++     since it may involve malicious code.  This security flaw was
+++     pointed out by Hiroshi Oota.
+++
+++     * ede/auto.el (ede-project-autoload): Add safe-p slot.
+++     (ede-project-class-files): Projects using Project.ede are unsafe.
+++     (ede-auto-load-project): New method.
+++
+++     * ede/simple.el (ede-project-class-files): Mark as unsafe.
+++
++ 2011-03-07  Chong Yidong  <cyd@stupidchicken.com>
++ 
++      * Version 23.3 released.
++diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
++index f0450d5..c3a223f 100644
++--- a/lisp/cedet/ede.el
+++++ b/lisp/cedet/ede.el
++@@ -94,6 +94,42 @@ target willing to take the file.  'never means never perform the check."
++   :group 'ede
++   :type 'sexp) ; make this be a list of options some day
++ 
+++(defcustom ede-project-directories nil
+++  "Directories in which EDE may search for project files.
+++If the value is t, EDE may search in any directory.
+++
+++If the value is a function, EDE calls that function with one
+++argument, the directory name; the function should return t iff
+++EDE should look for project files in the directory.
+++
+++Otherwise, the value should be a list of fully-expanded directory
+++names.  EDE searches for project files only in those directories.
+++If you invoke the commands \\[ede] or \\[ede-new] on a directory
+++that is not listed, Emacs will offer to add it to the list.
+++
+++Any other value disables searching for EDE project files."
+++  :group 'ede
+++  :type '(choice (const :tag "Any directory" t)
+++              (repeat :tag "List of directories"
+++                      (directory))
+++              (function :tag "Predicate"))
+++  :version "23.4"
+++  :risky t)
+++
+++(defun ede-directory-safe-p (dir)
+++  "Return non-nil if DIR is a safe directory to load projects from.
+++Projects that do not load a project definition as Emacs Lisp code
+++are safe, and can be loaded automatically.  Other project types,
+++such as those created with Project.ede files, are safe only if
+++specified by `ede-project-directories'."
+++  (setq dir (directory-file-name (expand-file-name dir)))
+++  ;; Load only if allowed by `ede-project-directories'.
+++  (or (eq ede-project-directories t)
+++      (and (functionp ede-project-directories)
+++        (funcall ede-project-directories dir))
+++      (and (listp ede-project-directories)
+++        (member dir ede-project-directories))))
+++
++ \f
++ ;;; Management variables
++ 
++@@ -419,24 +455,42 @@ provided `global-ede-mode' is enabled."
++ Sets buffer local variables for EDE."
++   (let* ((ROOT nil)
++       (proj (ede-directory-get-open-project default-directory
++-                                            'ROOT)))
+++                                            'ROOT))
+++      (projauto nil))
+++
++     (when (or proj ROOT
++-           (ede-directory-project-p default-directory t))
+++           ;; If there is no open project, look up the project
+++           ;; autoloader to see if we should initialize.
+++           (setq projauto (ede-directory-project-p default-directory t)))
+++
+++      (when (and (not proj) projauto)
+++
+++     ;; No project was loaded, but we have a project description
+++     ;; object.  This means that we can check if it is a safe
+++     ;; project to load before requesting it to be loaded.
++ 
++-      (when (not proj)
++-     ;; @todo - this could be wasteful.
++-     (setq proj (ede-load-project-file default-directory 'ROOT)))
+++     (when (or (oref projauto safe-p)
+++               ;; The project style is not safe, so check if it is
+++               ;; in `ede-project-directories'.
+++               (let ((top (ede-toplevel-project default-directory)))
+++                 (ede-directory-safe-p top)))
++ 
++-      (setq ede-object (ede-buffer-object (current-buffer)
+++       ;; The project is safe, so load it in.
+++       (setq proj (ede-load-project-file default-directory 'ROOT))))
+++
+++      ;; Only initialize EDE state in this buffer if we found a project.
+++      (when proj
+++
+++     (setq ede-object (ede-buffer-object (current-buffer)
++                                        'ede-object-project))
++ 
++-      (setq ede-object-root-project
++-         (or ROOT (ede-project-root ede-object-project)))
+++     (setq ede-object-root-project
+++           (or ROOT (ede-project-root ede-object-project)))
++ 
++-      (if (and (not ede-object) ede-object-project)
++-       (ede-auto-add-to-target))
+++     (if (and (not ede-object) ede-object-project)
+++         (ede-auto-add-to-target))
++ 
++-      (ede-apply-target-options))))
+++     (ede-apply-target-options)))))
++ 
++ (defun ede-reset-all-buffers (onoff)
++   "Reset all the buffers due to change in EDE.
++@@ -555,13 +609,73 @@ of objects with the `ede-want-file-p' method."
++ \f
++ ;;; Interactive method invocations
++ ;;
++-(defun ede (file)
++-  "Start up EDE on something.
++-Argument FILE is the file or directory to load a project from."
++-  (interactive "fProject File: ")
++-  (if (not (file-exists-p file))
++-      (ede-new file)
++-    (ede-load-project-file (file-name-directory file))))
+++(defun ede (dir)
+++  "Start up EDE for directory DIR.
+++If DIR has an existing project file, load it.
+++Otherwise, create a new project for DIR."
+++  (interactive
+++   ;; When choosing a directory to turn on, and we see some directory here,
+++   ;; provide that as the default.
+++   (let* ((top (ede-toplevel-project default-directory))
+++       (promptdflt (or top default-directory)))
+++     (list (read-directory-name "Project directory: "
+++                             promptdflt promptdflt t))))
+++  (unless (file-directory-p dir)
+++    (error "%s is not a directory" dir))
+++  (when (ede-directory-get-open-project dir)
+++    (error "%s already has an open project associated with it" dir))
+++
+++  ;; Check if the directory has been added to the list of safe
+++  ;; directories.  It can also add the directory to the safe list if
+++  ;; the user chooses.
+++  (if (ede-check-project-directory dir)
+++      (progn
+++     ;; If there is a project in DIR, load it, otherwise do
+++     ;; nothing.
+++     (ede-load-project-file dir)
+++
+++     ;; Check if we loaded anything on the previous line.
+++     (if (ede-current-project dir)
+++
+++         ;; We successfully opened an existing project.  Some open
+++         ;; buffers may also be referring to this project.
+++         ;; Resetting all the buffers will get them to also point
+++         ;; at this new open project.
+++         (ede-reset-all-buffers 1)
+++
+++       ;; ELSE
+++       ;; There was no project, so switch to `ede-new' which is how
+++       ;; a user can select a new kind of project to create.
+++       (let ((default-directory (expand-file-name dir)))
+++         (call-interactively 'ede-new))))
+++
+++    ;; If the proposed directory isn't safe, then say so.
+++    (error "%s is not an allowed project directory in `ede-project-directories'"
+++        dir)))
+++
+++(defun ede-check-project-directory (dir)
+++  "Check if DIR should be in `ede-project-directories'.
+++If it is not, try asking the user if it should be added; if so,
+++add it and save `ede-project-directories' via Customize.
+++Return nil iff DIR should not be in `ede-project-directories'."
+++  (setq dir (directory-file-name (expand-file-name dir))) ; strip trailing /
+++  (or (eq ede-project-directories t)
+++      (and (functionp ede-project-directories)
+++        (funcall ede-project-directories dir))
+++      ;; If `ede-project-directories' is a list, maybe add it.
+++      (when (listp ede-project-directories)
+++     (or (member dir ede-project-directories)
+++         (when (y-or-n-p (format "`%s' is not listed in `ede-project-directories'.
+++Add it to the list of allowed project directories? "
+++                                 dir))
+++           (push dir ede-project-directories)
+++           ;; If possible, save `ede-project-directories'.
+++           (if (or custom-file user-init-file)
+++               (let ((coding-system-for-read nil))
+++                 (customize-save-variable
+++                  'ede-project-directories
+++                  ede-project-directories)))
+++           t)))))
++ 
++ (defun ede-new (type &optional name)
++   "Create a new project starting of project type TYPE.
++@@ -596,6 +710,11 @@ Optional argument NAME is the name to give this project."
++     (error "Cannot create project in non-existent directory %s" default-directory))
++   (when (not (file-writable-p default-directory))
++     (error "No write permissions for %s" default-directory))
+++  (unless (ede-check-project-directory default-directory)
+++    (error "%s is not an allowed project directory in `ede-project-directories'"
+++        default-directory))
+++  ;; Make sure the project directory is loadable in the future.
+++  (ede-check-project-directory default-directory)
++   ;; Create the project
++   (let* ((obj (object-assoc type 'name ede-project-class-files))
++       (nobj (let ((f (oref obj file))
++@@ -629,6 +748,10 @@ Optional argument NAME is the name to give this project."
++      (ede-add-subproject pp nobj)
++      (ede-commit-project pp)))
++     (ede-commit-project nobj))
+++  ;; Once the project is created, load it again.  This used to happen
+++  ;; lazily, but with project loading occurring less often and with
+++  ;; security in mind, this is now the safe time to reload.
+++  (ede-load-project-file default-directory)
++   ;; Have the menu appear
++   (setq ede-minor-mode t)
++   ;; Allert the user
++@@ -651,11 +774,16 @@ ARGS are additional arguments to pass to method sym."
++ (defun ede-rescan-toplevel ()
++   "Rescan all project files."
++   (interactive)
++-  (let ((toppath (ede-toplevel-project default-directory))
++-     (ede-deep-rescan t))
++-    (project-rescan (ede-load-project-file toppath))
++-    (ede-reset-all-buffers 1)
++-    ))
+++  (if (not (ede-directory-get-open-project default-directory))
+++      ;; This directory isn't open.  Can't rescan.
+++      (error "Attempt to rescan a project that isn't open")
+++
+++    ;; Continue
+++    (let ((toppath (ede-toplevel-project default-directory))
+++       (ede-deep-rescan t))
+++
+++      (project-rescan (ede-load-project-file toppath))
+++      (ede-reset-all-buffers 1))))
++ 
++ (defun ede-new-target (&rest args)
++   "Create a new target specific to this type of project file.
++@@ -891,7 +1019,7 @@ Optional ROOTRETURN will return the root project for DIR."
++   ;; Do the load
++   ;;(message "EDE LOAD : %S" file)
++   (let* ((file dir)
++-      (path (expand-file-name (file-name-directory file)))
+++      (path (file-name-as-directory (expand-file-name dir)))
++       (pfc (ede-directory-project-p path))
++       (toppath nil)
++       (o nil))
++@@ -920,13 +1048,11 @@ Optional ROOTRETURN will return the root project for DIR."
++       ;; See if it's been loaded before
++       (setq o (object-assoc (ede-dir-to-projectfile pfc toppath) 'file
++                          ede-projects))
++-      (if (not o)
++-       ;; If not, get it now.
++-       (let ((ede-constructing pfc))
++-         (setq o (funcall (oref pfc load-type) toppath))
++-         (when (not o)
++-           (error "Project type error: :load-type failed to create a project"))
++-         (ede-add-project-to-global-list o)))
+++
+++      ;; If not open yet, load it.
+++      (unless o
+++     (let ((ede-constructing pfc))
+++       (setq o (ede-auto-load-project pfc toppath))))
++ 
++       ;; Return the found root project.
++       (when rootreturn (set rootreturn o))
++@@ -980,13 +1106,7 @@ Optional argument OBJ is an object to find the parent of."
++           (and root
++                (ede-find-subproject-for-directory root updir))
++           ;; Try the all structure based search.
++-          (ede-directory-get-open-project updir)
++-          ;; Load up the project file as a last resort.
++-          ;; Last resort since it uses file-truename, and other
++-          ;; slow features.
++-          (and (ede-directory-project-p updir)
++-               (ede-load-project-file
++-                (file-name-as-directory updir))))))))))
+++          (ede-directory-get-open-project updir))))))))
++ 
++ (defun ede-current-project (&optional dir)
++   "Return the current project file.
++@@ -1000,11 +1120,7 @@ If optional DIR is provided, get the project for DIR instead."
++     ;; No current project.
++     (when (not ans)
++       (let* ((ldir (or dir default-directory)))
++-     (setq ans (ede-directory-get-open-project ldir))
++-     (or ans
++-         ;; No open project, if this dir pass project-p, then load.
++-         (when (ede-directory-project-p ldir)
++-           (setq ans (ede-load-project-file ldir))))))
+++     (setq ans (ede-directory-get-open-project ldir))))
++     ;; Return what we found.
++     ans))
++ 
++@@ -1059,12 +1175,13 @@ If TARGET belongs to a subproject, return that project file."
++   "Return the project which is the parent of TARGET.
++ It is recommended you track the project a different way as this function
++ could become slow in time."
++-  ;; @todo - use ede-object-project as a starting point.
++-  (let ((ans nil) (projs ede-projects))
++-    (while (and (not ans) projs)
++-      (setq ans (ede-target-in-project-p (car projs) target)
++-         projs (cdr projs)))
++-    ans))
+++  (or ede-object-project
+++      ;; If not cached, derive it from the current directory of the target.
+++      (let ((ans nil) (projs ede-projects))
+++     (while (and (not ans) projs)
+++       (setq ans (ede-target-in-project-p (car projs) target)
+++             projs (cdr projs)))
+++     ans)))
++ 
++ (defmethod ede-find-target ((proj ede-project) buffer)
++   "Fetch the target in PROJ belonging to BUFFER or nil."
++diff --git a/lisp/cedet/ede/auto.el b/lisp/cedet/ede/auto.el
++index 36f902d..0d84ee4 100644
++--- a/lisp/cedet/ede/auto.el
+++++ b/lisp/cedet/ede/auto.el
++@@ -58,6 +58,13 @@ associated with a single object class, based on the initilizeres used.")
++        :initform t
++        :documentation
++        "Non-nil if this is an option when a user creates a project.")
+++   (safe-p :initarg :safe-p
+++        :initform t
+++        :documentation
+++        "Non-nil if the project load files are \"safe\".
+++An unsafe project is one that loads project variables via Emacs
+++Lisp code.  A safe project is one that loads project variables by
+++scanning files without loading Lisp code from them.")
++    )
++   "Class representing minimal knowledge set to run preliminary EDE functions.
++ When more advanced functionality is needed from a project type, that projects
++@@ -69,13 +76,15 @@ type is required and the load function used.")
++                       :name "Make" :file 'ede/proj
++                       :proj-file "Project.ede"
++                       :load-type 'ede-proj-load
++-                      :class-sym 'ede-proj-project)
+++                      :class-sym 'ede-proj-project
+++                      :safe-p nil)
++    (ede-project-autoload "edeproject-automake"
++                       :name "Automake" :file 'ede/proj
++                       :proj-file "Project.ede"
++                       :initializers '(:makefile-type Makefile.am)
++                       :load-type 'ede-proj-load
++-                      :class-sym 'ede-proj-project)
+++                      :class-sym 'ede-proj-project
+++                      :safe-p nil)
++    (ede-project-autoload "automake"
++                       :name "automake" :file 'ede/project-am
++                       :proj-file "Makefile.am"
++@@ -84,6 +93,8 @@ type is required and the load function used.")
++                       :new-p nil))
++   "List of vectors defining how to determine what type of projects exist.")
++ 
+++(put 'ede-project-class-files 'risky-local-variable t)
+++
++ ;;; EDE project-autoload methods
++ ;;
++ (defmethod ede-project-root ((this ede-project-autoload))
++@@ -122,6 +133,19 @@ Return nil if the project file does not exist."
++     (when (and f (file-exists-p f))
++       f)))
++ 
+++(defmethod ede-auto-load-project ((this ede-project-autoload) dir)
+++  "Load in the project associated with THIS project autoload description.
+++THIS project description should be valid for DIR, where the project will
+++be loaded."
+++  ;; Last line of defense: don't load unsafe projects.
+++  (when (not (or (oref this :safe-p)
+++              (ede-directory-safe-p dir)))
+++    (error "Attempt to load an unsafe project (bug elsewhere in EDE)"))
+++  ;; Things are good - so load the project.
+++  (let ((o (funcall (oref this load-type) dir)))
+++    (when (not o)
+++      (error "Project type error: :load-type failed to create a project"))
+++    (ede-add-project-to-global-list o)))
++ 
++ (provide 'ede/auto)
++ 
++diff --git a/lisp/cedet/ede/simple.el b/lisp/cedet/ede/simple.el
++index 14b3a04..829c085 100644
++--- a/lisp/cedet/ede/simple.el
+++++ b/lisp/cedet/ede/simple.el
++@@ -50,7 +50,8 @@
++            :name "Simple" :file 'ede/simple
++            :proj-file 'ede-simple-projectfile-for-dir
++            :load-type 'ede-simple-load
++-           :class-sym 'ede-simple-project)
+++           :class-sym 'ede-simple-project
+++           :safe-p nil)
++           t)
++ 
++ (defcustom ede-simple-save-directory "~/.ede"
index 21e9c3cc54a5232416c2720d3d4a4b83b7731ec5,0000000000000000000000000000000000000000..e033d48452d28755bb29d0b32161fb979565f112
mode 100644,000000..100644
--- /dev/null
@@@ -1,17 -1,0 +1,18 @@@
 +0001-Prefer-usr-share-info-emacs-23-over-usr-share-info.patch
 +0002-Run-debian-startup-and-set-debian-emacs-flavor.patch
 +0003-Remove-files-that-appear-to-be-incompatible-with-the.patch
 +0004-Adjust-documentation-references-for-Debian.patch
 +0005-Cause-the-build-to-fail-if-liblockfile-isn-t-selecte.patch
 +0006-Avoid-silently-losing-mail-via-fakemail.patch
 +0007-Modify-the-output-of-version-to-indicate-Debian-modi.patch
 +0008-Look-for-NEWS-in-order-to-find-etc-rather-than-GNU.patch
 +0009-Invoke-the-correct-xmlstarlet-executable-on-Debian-s.patch
 +0010-Fix-startup-hang-on-Debian-GNU-kFreeBSD.patch
 +0011-Don-t-clear-FONTCONFIG_LIBS-and-FONTCONFIG_CFLAGS-in.patch
 +0012-Fix-a-tty-related-preprocessor-inclusion-error-affec.patch
 +0013-Expect-0-from-kill-for-zombies-on-GNU-Hurd.patch
 +0014-Add-i386-to-cpp_undefs-in-configure.in-to-fix-i386-m.patch
 +0015-Look-for-crt1.o-in-the-correct-multiarch-location.patch
 +0016-Use-CRT_DIR-to-find-crt-.o-on-ppc64.patch
 +0017-Define-POSIX_SIGNALS-for-GNU-Hurd.patch
++0018-Don-t-let-CEDET-execute-code-from-an-arbitrary-Proje.patch